/**********************************************************************

   Audacity - A Digital Audio Editor
   Copyright 1999-2018 Audacity Team
   File License: wxWidgets

   Stephen Parry
   James Crook

******************************************************************//**

\file OpenSaveCommands.cpp
\brief Contains definitions for the OpenProjectCommand and SaveProjectCommand classes

*//*******************************************************************/

#include "OpenSaveCommands.h"

#include "CommandDispatch.h"
#include "MenuRegistry.h"
#include "../CommonCommandFlags.h"
#include "LoadCommands.h"
#include "AudacityLogger.h"
#include "Project.h"
#include "ProjectFileIO.h"
#include "../ProjectFileManager.h"
#include "../ProjectManager.h"
#include "Export.h"
#include "SettingsVisitor.h"
#include "ShuttleGui.h"
#include "CommandContext.h"

const ComponentInterfaceSymbol OpenProjectCommand::Symbol
{ XO("Open Project2") };

namespace {
BuiltinCommandsModule::Registration< OpenProjectCommand > reg;
}

template<bool Const>
bool OpenProjectCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    S.Define(mFileName, wxT("Filename"), wxString { "test.aup3" });
    S.OptionalN(bHasAddToHistory).Define(mbAddToHistory, wxT("AddToHistory"),  false);
    return true;
}

bool OpenProjectCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool OpenProjectCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

void OpenProjectCommand::PopulateOrExchange(ShuttleGui& S)
{
    S.AddSpace(0, 5);

    S.StartMultiColumn(2, wxALIGN_CENTER);
    {
        S.TieTextBox(XXO("File Name:"), mFileName);
        S.TieCheckBox(XXO("Add to History"), mbAddToHistory);
    }
    S.EndMultiColumn();
}

bool OpenProjectCommand::Apply(const CommandContext& context)
{
    auto& projectFileIO = ProjectFileIO::Get(context.project);

    auto oldFileName = projectFileIO.GetFileName();
    if (mFileName.empty()) {
        // This path queries the user for files to open
        auto project = &context.project;
        // Error check?
        ProjectManager::OpenFiles(project);
    } else {
        ProjectManager::ProjectChooser chooser{ &context.project, true };
        if (ProjectFileManager::OpenFile(
                std::ref(chooser), mFileName, mbAddToHistory)) {
            chooser.Commit();
        }
    }
    const auto& newFileName = projectFileIO.GetFileName();

    // Because Open does not return a success or failure, we have to guess
    // at this point, based on whether the project file name has
    // changed and what to...
    return !newFileName.empty() && newFileName != oldFileName;
}

const ComponentInterfaceSymbol SaveProjectCommand::Symbol
{ XO("Save Project2") };

namespace {
BuiltinCommandsModule::Registration< SaveProjectCommand > reg2;
}

template<bool Const>
bool SaveProjectCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    S.Define(mFileName, wxT("Filename"), wxString { "name.aup3" });
    S.Define(mbAddToHistory, wxT("AddToHistory"),  false);
    return true;
}

bool SaveProjectCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool SaveProjectCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

void SaveProjectCommand::PopulateOrExchange(ShuttleGui& S)
{
    S.AddSpace(0, 5);

    S.StartMultiColumn(2, wxALIGN_CENTER);
    {
        S.TieTextBox(XXO("File Name:"), mFileName);
        S.TieCheckBox(XXO("Add to History"), mbAddToHistory);
    }
    S.EndMultiColumn();
}

bool SaveProjectCommand::Apply(const CommandContext& context)
{
    auto& projectFileManager = ProjectFileManager::Get(context.project);
    if (mFileName.empty()) {
        return projectFileManager.SaveAs();
    } else {
        return projectFileManager.SaveAs(mFileName, mbAddToHistory);
    }
}

const ComponentInterfaceSymbol SaveCopyCommand::Symbol
{ XO("Save Copy") };

namespace {
BuiltinCommandsModule::Registration< SaveCopyCommand > reg3;
}

template<bool Const>
bool SaveCopyCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    S.Define(mFileName, wxT("Filename"), wxString { "name.aup3" });
    return true;
}

bool SaveCopyCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool SaveCopyCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

void SaveCopyCommand::PopulateOrExchange(ShuttleGui& S)
{
    S.AddSpace(0, 5);

    S.StartMultiColumn(2, wxALIGN_CENTER);
    {
        S.TieTextBox(XXO("File Name:"), mFileName);
    }
    S.EndMultiColumn();
}

bool SaveCopyCommand::Apply(const CommandContext& context)
{
    auto& projectFileManager = ProjectFileManager::Get(context.project);
    return projectFileManager.SaveCopy(mFileName);
}

const ComponentInterfaceSymbol SaveLogCommand::Symbol
{ XO("Save Log") };

namespace {
BuiltinCommandsModule::Registration< SaveLogCommand > reg4;
}

template<bool Const>
bool SaveLogCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    S.Define(mFileName, wxT("Filename"), wxString { "log.txt" });
    return true;
}

bool SaveLogCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool SaveLogCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

void SaveLogCommand::PopulateOrExchange(ShuttleGui& S)
{
    S.AddSpace(0, 5);

    S.StartMultiColumn(2, wxALIGN_CENTER);
    {
        S.TieTextBox(XXO("File Name:"), mFileName);
    }
    S.EndMultiColumn();
}

bool SaveLogCommand::Apply(const CommandContext& context)
{
    auto logger = AudacityLogger::Get();
    return logger->SaveLog(mFileName);
}

const ComponentInterfaceSymbol ClearLogCommand::Symbol
{ XO("Clear Log") };

namespace {
BuiltinCommandsModule::Registration< ClearLogCommand > reg5;
}

template<bool Const>
bool ClearLogCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    return true;
}

bool ClearLogCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool ClearLogCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

bool ClearLogCommand::PromptUser(AudacityProject& project)
{
    return true;
}

bool ClearLogCommand::Apply(const CommandContext& context)
{
    auto logger = AudacityLogger::Get();
    return logger->ClearLog();
}

namespace {
using namespace MenuRegistry;

// Register menu items

AttachedItem sAttachment{
    Items(wxT(""),
          // Note that the PLUGIN_SYMBOL must have a space between words,
          // whereas the short-form used here must not.
          // (So if you did write "Compare Audio" for the PLUGIN_SYMBOL name, then
          // you would have to use "CompareAudio" here.)
          Command(wxT("OpenProject2"), XXO("Open Project..."),
                  CommandDispatch::OnAudacityCommand, AudioIONotBusyFlag()),
          Command(wxT("SaveProject2"), XXO("Save Project..."),
                  CommandDispatch::OnAudacityCommand, AudioIONotBusyFlag())
          ),
    wxT("Optional/Extra/Part2/Scriptables2")
};
}
